package webgamemaker.Common;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;



import com.google.gwt.user.client.Timer;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.events.DropMoveEvent;
import com.smartgwt.client.widgets.events.DropMoveHandler;
import com.smartgwt.client.widgets.events.MouseDownEvent;
import com.smartgwt.client.widgets.events.MouseDownHandler;
import com.smartgwt.client.widgets.events.MouseMoveEvent;
import com.smartgwt.client.widgets.events.MouseMoveHandler;

public class GameMap extends Canvas
{
	public MapData mapData;
	public GWTCanvas frontLayer;
	public GWTCanvas canvasLayer[];
	public int cursorX, cursorY, cursorWidth, cursorHeight;
	public ArrayList<Callback> selectCallback;
	public int frame;
	public boolean grid;
	
	public GameMap(final MapData mapData)
	{
		this.mapData = mapData;
		cursorX = -1;
		cursorY = -1;
		selectCallback = new ArrayList<Callback>();
		canvas_resize(mapData.width, mapData.height, mapData.num_layer);
		this.addMouseMoveHandler(new MouseMoveHandler()
		{
			public void onMouseMove(MouseMoveEvent event) 
			{
				cursorX = (event.getX()-getAbsoluteLeft())/mapData.tileWidth;
				cursorY = (event.getY()-getAbsoluteTop())/mapData.tileHeight;
				if(cursorX+cursorWidth > mapData.width || cursorY+cursorHeight > mapData.height)
					cursorX = -1;
				drawFrontLayer();
			}
		});
		this.addMouseDownHandler(new MouseDownHandler()
		{
			public void onMouseDown(MouseDownEvent event) 
			{
				cursorX = (event.getX()-getAbsoluteLeft())/mapData.tileWidth;
				cursorY = (event.getY()-getAbsoluteTop())/mapData.tileHeight;
				if(cursorX+cursorWidth > mapData.width && cursorY+cursorHeight > mapData.height)
					cursorX = -1;
				else
				{
					for(int i = 0; i < selectCallback.size(); i++)
						selectCallback.get(i).onCall(GameMap.this);
					drawFrontLayer();
				}
			}
			
		});
	}
	
	public void addSelectCallback(Callback callback)
	{
		selectCallback.add(callback);
	}
	
	public void resize(int width, int height, int num_layer)
	{
		mapData.resize(width, height, num_layer);
		canvas_resize(width, height, num_layer);
	}
	
	public void canvas_resize(int width, int height, int num_layer)
	{
		clear();
		canvasLayer = new GWTCanvas[num_layer];
		for(int k = 0; k < num_layer; k++)
		{
			canvasLayer[k] = new GWTCanvas();
			addChild(canvasLayer[k]);
		}
		frontLayer = new GWTCanvas();
		addChild(frontLayer);
	}
	
	public void redraw()
	{
		int width = mapData.width*mapData.tileWidth;
		int height = mapData.height*mapData.tileHeight;
		for(int i=0;i<mapData.num_layer; i++)
		{
			canvasLayer[i].setSize(width+"px", height+"px");
			canvasLayer[i].setPixelWidth(width);
			canvasLayer[i].setPixelHeight(height);
			canvasLayer[i].setCoordWidth(width);
			canvasLayer[i].setCoordHeight(height);
		}
		frontLayer.setSize(width+"px", height+"px");
		frontLayer.setPixelWidth(width);
		frontLayer.setPixelHeight(height);
		frontLayer.setCoordWidth(width);
		frontLayer.setCoordHeight(height);
		draw();
	}
	
	public void draw()
	{
		for(int k=0;k<mapData.num_layer;k++)
			drawCanvasLayer(k);
		drawFrontLayer();
	}
	
	public void drawCanvasLayer(int layer)
	{
		int x = 0, y = 0;
		Map<String, Object> param = new HashMap<String,Object>();
		boolean neighbour[] = new boolean[8];
		param.put("neighbour", neighbour);
		param.put("context", canvasLayer[layer]);
		canvasLayer[layer].clear();
		for(int i=0;i<mapData.width; i++)
		{
			for(int j=0;j<mapData.height;j++)
			{
				Tile tile = mapData.tiles[i+j*mapData.width][layer].tile;
				if(i != 0 && j != 0)
					neighbour[0] = (tile == mapData.tiles[i-1+(j-1)*mapData.width][layer].tile);
				else neighbour[0] = true;
				if(i != mapData.width-1 && j != 0)
					neighbour[2] = (tile == mapData.tiles[i+1+(j-1)*mapData.width][layer].tile);
				else neighbour[2] = true;
				if(i != 0 && j != mapData.height-1)
					neighbour[5] = (tile == mapData.tiles[i-1+(j+1)*mapData.width][layer].tile);
				else neighbour[5] = true;
				if(i != mapData.width-1 && j != mapData.height-1)
					neighbour[7] = (tile == mapData.tiles[i+1+(j+1)*mapData.width][layer].tile);
				else neighbour[7] = true;
				
				if(j != 0)
					neighbour[1] = (tile == mapData.tiles[i+(j-1)*mapData.width][layer].tile);
				else neighbour[1] = true;
				if(i != 0)
					neighbour[3] = (tile == mapData.tiles[i-1+j*mapData.width][layer].tile);
				else neighbour[3] = true;
				if(i != mapData.width-1)
					neighbour[4] = (tile == mapData.tiles[i+1+j*mapData.width][layer].tile);
				else neighbour[4] = true;
				if(j != mapData.height-1)
					neighbour[6] = (tile == mapData.tiles[i+(j+1)*mapData.width][layer].tile);
				else neighbour[6] = true;
				
				param.put("x", x);
				param.put("y", y);
				if(tile != null)
					tile.draw(param);
				y+=32;
			}
			y=0;
			x+=32;
		}
		x=0;	
	}
	
	public void drawFrontLayer()
	{
		frontLayer.clear();
		if(grid)
		{
			frontLayer.setLineWidth(1.0);
			frontLayer.beginPath();
			for(int i = 0; i <= mapData.width; i++)
			{
				frontLayer.moveTo(i*mapData.tileWidth, 0);
				frontLayer.lineTo(i*mapData.tileWidth, mapData.height*mapData.tileHeight);
			}
			for(int j = 0; j <= mapData.height; j++)
			{
				frontLayer.moveTo(0, j*mapData.tileHeight);
				frontLayer.lineTo(mapData.width*mapData.tileWidth, j*mapData.tileHeight);
			}
			frontLayer.stroke();
				
		}
		if(cursorWidth > 0 && cursorHeight > 0 && cursorX != -1 && cursorY != -1)
		{
			double initWidth = frontLayer.getLineWidth();
			frontLayer.setLineWidth(2.0);
			frontLayer.strokeRect(cursorX*mapData.tileWidth, cursorY*mapData.tileHeight, cursorWidth*mapData.tileWidth, cursorHeight*mapData.tileHeight);
			frontLayer.setLineWidth(initWidth);
		}
	}
}
